
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "option_parser.h"
#include "types.h"

#ifndef ADDRDEC_H
#define ADDRDEC_H

enum partition_index_function
{
  CONSECUTIVE = 0,
  BITWISE_PERMUTATION,
  IPOLY,
  PAE,
  RANDOM,
  CUSTOM
};

struct addrdec_t
{
  void print(FILE *fp) const;

  unsigned chip;
  unsigned bk;
  unsigned row;
  unsigned col;
  unsigned burst;

  unsigned sub_partition;
};

class linear_to_raw_address_translation
{
public:
  linear_to_raw_address_translation();
  void addrdec_setoption(option_parser_t opp);
  void init(unsigned int n_channel, unsigned int n_sub_partition_in_channel);

  // accessors
  void addrdec_tlx(addr_t addr, addrdec_t *tlx) const;
  addr_t partition_address(addr_t addr) const;

private:
  void addrdec_parseoption(const char *option);
  void sweep_test() const; // sanity check to ensure no overlapping

  enum
  {
    CHIP = 0,
    BK = 1,
    ROW = 2,
    COL = 3,
    BURST = 4,
    N_ADDRDEC
  };

  const char *addrdec_option;
  int simulator_mem_address_mask;
  partition_index_function memory_partition_indexing;
  bool run_test;

  int ADDR_CHIP_S;
  unsigned char addrdec_mklow[N_ADDRDEC];
  unsigned char addrdec_mkhigh[N_ADDRDEC];
  addr_t addrdec_mask[N_ADDRDEC];
  addr_t sub_partition_id_mask;

  unsigned int gap;
  unsigned m_n_channel;
  int m_n_sub_partition_in_channel;
  int m_n_sub_partition_total;
  unsigned log2channel;
  unsigned log2sub_partition;
  unsigned nextPowerOf2_m_n_channel;
};

#endif
